﻿/*
 *作者:陈佳
 *时间:2017/07/10
  */
namespace System.Collections.Generic
{
	using System;
	/// <summary>
	/// 异步队列,用于多个线程入队,一个线程出队消费
	/// this Queue use to multiple thread Enqueue and one thread dequeue;
	/// not use to multiple thread dequeue
	/// </summary>
	/// <typeparam name="T"></typeparam>

	public class QueueAsync<T>
	{
		private Queue<T> mEnque;
		private Queue<T> mDeque;
		//private int queueNum = 2;
		private readonly object mLocker = new object();
		public QueueAsync()
		{
			mEnque = new Queue<T>();
			mDeque = new Queue<T>();
		}
		public QueueAsync(int size)
		{
			mEnque = new Queue<T>(size);
			mDeque = new Queue<T>(size);
		}
		#region 公共接口函数
		/// <summary>
		/// 入队一个实例,可以多个线程入队
		/// </summary>
		/// <param name="item"></param>
		public void Enqueue(T item)
		{
			lock (mLocker)
			{
				mEnque.Enqueue(item);
			}
		}

		/// <summary>
		/// 当前队列的元素数量
		/// </summary>
		public int Count
		{
			get
			{
				lock (mLocker)
				{
					return mDeque.Count + mEnque.Count;
				}
			}
		}
		/// <summary>
		/// 查看最前面的元素
		/// </summary>
		/// <returns></returns>
		public T Peek()
		{
			T value;
			if (Count > 0)
			{
				if (mDeque.Count == 0)
				{
					swap();
				}
				value = mDeque.Peek();
			}
			else
			{
				value = default(T);
			}
			return value;
		}
		/// <summary>
		/// 取出一个元素
		/// </summary>
		/// <returns></returns>
		public T Dequeue()
		{
			T value;
			if (Count > 0)
			{
				if (mDeque.Count == 0)
				{
					swap();
				}
				value = dequeueUnsafe();
			}
			else
			{
				value = default(T);
			}
			return value;
		}

		/// <summary>
		/// 出队所有的实例,仅在一个线程出队
		/// dequeue All in outQue items only used one thread
		/// </summary>
		/// <param name="func"></param>
		public void DequeueAll(Action<T> func)
		{
			if (func == null)
			{
				return;
			}
			while (mDeque.Count > 0)
			{
				T it = dequeueUnsafe();
				func(it);
			}
			swap();
		}
		public void Clear()
		{
			mDeque.Clear();
			swap();
			mDeque.Clear();
		}
		#endregion
		#region 私有函数

		private T dequeueUnsafe()
		{
			return mDeque.Dequeue();
		}
		/// <summary>
		/// 交换入和出队列
		/// </summary>
		private void swap()
		{
			lock (mLocker)
			{
				var temp = mEnque;
				mEnque = mDeque;
				mDeque = temp;
			}
		}
		#endregion
	}
}